<?php
/**
 * 简单反射处理类
 * 替代 roave/better-reflection 包的功能
 */

namespace app\common\library;

class SimpleReflection
{
    /**
     * 获取类的方法列表
     * @param string $className 类名
     * @return array 方法列表
     */
    public static function getClassMethods($className)
    {
        if (!class_exists($className)) {
            return [];
        }
        
        $methods = [];
        $reflection = new \ReflectionClass($className);
        foreach ($reflection->getMethods() as $method) {
            $methods[] = [
                'name' => $method->getName(),
                'isPublic' => $method->isPublic(),
                'isProtected' => $method->isProtected(),
                'isPrivate' => $method->isPrivate(),
                'isStatic' => $method->isStatic(),
                'parameters' => self::getMethodParameters($method)
            ];
        }
        
        return $methods;
    }
    
    /**
     * 获取方法的参数列表
     * @param \ReflectionMethod $method 方法反射对象
     * @return array 参数列表
     */
    private static function getMethodParameters($method)
    {
        $parameters = [];
        foreach ($method->getParameters() as $param) {
            $paramInfo = [
                'name' => $param->getName(),
                'hasType' => $param->hasType(),
                'isOptional' => $param->isOptional(),
                'isDefaultValueAvailable' => $param->isDefaultValueAvailable()
            ];
            
            if ($param->hasType()) {
                $paramInfo['type'] = (string) $param->getType();
            }
            
            if ($param->isDefaultValueAvailable()) {
                try {
                    $paramInfo['defaultValue'] = $param->getDefaultValue();
                } catch (\ReflectionException $e) {
                    $paramInfo['defaultValue'] = null;
                }
            }
            
            $parameters[] = $paramInfo;
        }
        
        return $parameters;
    }
    
    /**
     * 获取类的属性列表
     * @param string $className 类名
     * @return array 属性列表
     */
    public static function getClassProperties($className)
    {
        if (!class_exists($className)) {
            return [];
        }
        
        $properties = [];
        $reflection = new \ReflectionClass($className);
        foreach ($reflection->getProperties() as $property) {
            $properties[] = [
                'name' => $property->getName(),
                'isPublic' => $property->isPublic(),
                'isProtected' => $property->isProtected(),
                'isPrivate' => $property->isPrivate(),
                'isStatic' => $property->isStatic()
            ];
        }
        
        return $properties;
    }
    
    /**
     * 获取类的常量列表
     * @param string $className 类名
     * @return array 常量列表
     */
    public static function getClassConstants($className)
    {
        if (!class_exists($className)) {
            return [];
        }
        
        $constants = [];
        $reflection = new \ReflectionClass($className);
        foreach ($reflection->getConstants() as $name => $value) {
            $constants[] = [
                'name' => $name,
                'value' => $value
            ];
        }
        
        return $constants;
    }
    
    /**
     * 获取类的父类
     * @param string $className 类名
     * @return string|null 父类名
     */
    public static function getParentClass($className)
    {
        if (!class_exists($className)) {
            return null;
        }
        
        $reflection = new \ReflectionClass($className);
        $parent = $reflection->getParentClass();
        return $parent ? $parent->getName() : null;
    }
    
    /**
     * 获取类实现的接口
     * @param string $className 类名
     * @return array 接口列表
     */
    public static function getClassInterfaces($className)
    {
        if (!class_exists($className)) {
            return [];
        }
        
        $interfaces = [];
        $reflection = new \ReflectionClass($className);
        foreach ($reflection->getInterfaces() as $interface) {
            $interfaces[] = $interface->getName();
        }
        
        return $interfaces;
    }
    
    /**
     * 分析PHP文件中的类
     * @param string $filePath 文件路径
     * @return array 类信息
     */
    public static function analyzeFile($filePath)
    {
        if (!file_exists($filePath)) {
            return [];
        }
        
        $classes = [];
        $tokens = token_get_all(file_get_contents($filePath));
        $namespace = '';
        $className = '';
        
        for ($i = 0; $i < count($tokens); $i++) {
            if ($tokens[$i][0] === T_NAMESPACE) {
                $i++;
                while (isset($tokens[$i]) && is_array($tokens[$i]) && $tokens[$i][0] !== T_STRING) {
                    $i++;
                }
                $namespace = '';
                while (isset($tokens[$i]) && is_array($tokens[$i]) && ($tokens[$i][0] === T_STRING || $tokens[$i][0] === T_NS_SEPARATOR)) {
                    $namespace .= $tokens[$i][1];
                    $i++;
                }
            }
            
            if ($tokens[$i][0] === T_CLASS) {
                $i++;
                while (isset($tokens[$i]) && !is_array($tokens[$i])) {
                    $i++;
                }
                if (isset($tokens[$i]) && is_array($tokens[$i])) {
                    $className = $tokens[$i][1];
                    $fullClassName = $namespace ? $namespace . '\\' . $className : $className;
                    $classes[] = [
                        'name' => $fullClassName,
                        'shortName' => $className,
                        'namespace' => $namespace,
                        'methods' => self::getClassMethods($fullClassName),
                        'properties' => self::getClassProperties($fullClassName),
                        'constants' => self::getClassConstants($fullClassName),
                        'parent' => self::getParentClass($fullClassName),
                        'interfaces' => self::getClassInterfaces($fullClassName)
                    ];
                }
            }
        }
        
        return $classes;
    }
}